#include <iostream>
#include <functional>
#include <stdint.h>
#include <memory>
#include <vector>
#include <unordered_map>
#include <unistd.h>






//定时器任务, 
using TaskFunc = std::function<void()>;
using ReleaseFunc = std::function<void()>; 
class TimerTask{
private:
    uint64_t _id;       //定时器任务id
    uint32_t _timeout;  //定时器任务超时时间
    bool _concel;       //定时器任务是否被取消 false ->没有被取消,  true -> 被取消了 
    TaskFunc _task_callback; // 定时器任务对象执行的函数
    ReleaseFunc _release; // 用于删除 TimerWheel 中保存的有关此任务的所有对象信息 //也在析构的执行, 

public:
    TimerTask(uint64_t id, uint32_t timeout ,TaskFunc task_collback):_id(id), _timeout(timeout), _task_callback(task_collback) {}
    ~TimerTask(){if(_concel == false){ _task_callback(); } _release(); }
    void SetRelease(const ReleaseFunc& release){_release = release;} //设置删除回调
    uint32_t GetTimeOut (){ return _timeout; }
    void Cancel() { _concel = true; }
};


class TimerWheel{
private:
    using TaskWeak_Ptr = std::weak_ptr<TimerTask>;
    using TaskShared_Ptr = std::shared_ptr<TimerTask>;
    int _tick; //当前指针
    int _capacity; // 时间轮大小
    std::vector<std::vector<TaskShared_Ptr>> _wheel; //时间轮数组
    std::unordered_map <uint64_t , TaskWeak_Ptr> _timers; //保存, 定时器任务id 和 定时器任务指针之间的关联关系
    //注意这里不能使用shared_ptr, 

public:
    TimerWheel():_tick(0), _capacity(60), _wheel(_capacity){}
    void TimerAdd (uint64_t id, uint32_t timeout ,TaskFunc task_collback) //添加定时任务
    {
        TaskShared_Ptr pt(new TimerTask(id, timeout, task_collback)); 
        pt->SetRelease(std::bind(&TimerWheel::RemoveTimer, this, id));
        _timers[id] = TaskWeak_Ptr(pt);
        int pos = _tick + timeout;
        _wheel[pos % _capacity].push_back(pt);
    }
    void TimerFlush (uint64_t id ) //刷新定时任务时间 , 就是在当前tick 后, timeout 位置再添加一个 TaskShared_Ptr, 防止TaskShared_Ptr, 析构不被执行
    {
        auto it = _timers.find(id);
        if(it == _timers.end()){
            return; //没有找到当前 id 对应的 定时器任务 
        }
        TaskShared_Ptr pt(it->second.lock()); // 通过定时器任务的 weak_ptr 构建一个 shared_ptr ;
        int pos = _tick + pt->GetTimeOut();
        _wheel[pos % _capacity].push_back(pt); //这样前面一个 定时器任务对象 被释放的时候, 就不会执行析构函数
    }
    void TimerCancel(uint64_t id){
        auto it = _timers.find(id);
        if(it == _timers.end()){
            return ;
        }
        // it->second.Cancel(); //weak_ptr 没有提供 operator* 解引用和 operator-> 所以要传化为 sherad_ptr 
        it->second.lock()->Cancel();
    }

    //这个函数每秒被执行一次 , 相当于每秒_tick 向后移动一步
    void RunTimerTask(){
        
        _wheel[_tick].clear(); //清空 vector, 直接智能指针就调用析构函数(如果智能指针内部的计数器为0)
        _tick = (_tick + 1)% _capacity;
    }

    
private:
    void RemoveTimer(uint64_t id){
        auto it = _timers.find(id);
        if(it != _timers.end()){
            _timers.erase(id);
        }
    }

};


void dele(){
    std::cout<< "定时任务触发 "<<std::endl;
}

int main(){

    TimerWheel tw;
    tw.TimerAdd (888, 5, dele);
    for(int i=0; i< 5 ;i++)
    {

        tw.TimerFlush(888);
        std::cout<< " 定时任务被刷新了 "<< std::endl;
        tw.RunTimerTask();
        sleep(1);
    }
    tw.TimerCancel(888);
    int n =10;
    while(n--){
        sleep(1);
        std::cout<< "-------------------"<<std::endl;
        tw.RunTimerTask();
    }
    return 0;
}